import asyncio
from tkinter import *
from PIL import Image, ImageTk
import cv2
import features as f

tk = Tk()
tk.title("人证识别系统 - 1420实验室")

canvas = Canvas(tk, width=400, height=380, bg='#f0f0f0')
capture = cv2.VideoCapture(0)

# 定义提示信息
tip_msg = "人证识别系统 - 初始化"
label = Label(tk, text=tip_msg, fg="black", bg="#f0f0f0", font=30, height=3, wraplength=400)
label.pack()

# 人脸模型
face_cascade = cv2.CascadeClassifier('lbpcascade_frontalface.xml')

stable = 0
working = False
result = False
initial = True


def com(img_a, sid):
    global result

    if f.compare(img_a, sid):
        result = 1
    else:
        result = 2


while True:
    ret, frame = capture.read()

    # 读卡获取学号
    ff = open('xuehao.txt', 'r')
    stu_id = ff.read()

    if stu_id == '':
        tip_msg = '请刷校园卡！'
    else:
        if f.has_pic(stu_id):
            # 查找人脸（灰度）
            gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
            faces = face_cascade.detectMultiScale(gray)

            for (x, y, w, h) in faces:
                font = cv2.FONT_HERSHEY_COMPLEX
                cv2.rectangle(frame, (x, y), (x + w, y + h), (123, 104, 238), 2)

                # 当稳定值增加到45时开始识别
                if stable == 45 and not working:
                    working = True
                    # 裁剪图像
                    roi = frame[y:y + h, x:x + w]
                    # 编码图像
                    img_a_base64 = f.image_to_base64(roi)
                    # 识别图像（多线程非阻塞）
                    loop = asyncio.get_event_loop()
                    loop.run_in_executor(None, com, img_a_base64, stu_id)

            # 当没有人脸时快速降低stable值
            if len(faces) == 0:
                tip_msg = "请移至摄像机框内开始识别"
                if stable > 0:
                    stable -= 10
                else:
                    working = False
                    result = False
            else:
                if stable < 50:
                    stable += 1

            if working:
                tip_msg = "正在识别..."
            else:
                if stable > 20:
                    tip_msg = "请勿移动，正在拍照..."

            # 轮询识别结果
            if result == 1:
                tip_msg = "欢迎：" + stu_id
            elif result == 2:
                tip_msg = "抱歉：人证不匹配"
        else:
            tip_msg = "数据库无此学号，请录入"

    # 显示提示信息
    label.config(text=tip_msg)

    # 显示摄像机，当没有人脸时高斯模糊
    if stable < 5 or result > 0:
        frame = cv2.blur(frame, (30, 30))
    img = Image.fromarray(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
    img = ImageTk.PhotoImage(image=img)
    canvas.create_image((150, 150), image=img)
    canvas.pack()

    if initial:
        initial = False

        intro = "使用方法：\n      将校园卡放置于刷卡器上，屏幕上显示证件对应的“姓名”、“学号”，然后进行人脸识别和体温测量，当人证匹配且体温正常时，门禁可自动打开。"
        intro = Label(tk, text=intro, fg="white", bg="#6495ED", height=4, padx=10, pady=10, wraplength=380,
                      justify='left')
        intro.pack()

    # 更新画布
    tk.update()
